package test.administrator.example.com.mvptest1.framework.support.manager;

import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.ContextWrapper;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.util.ArrayMap;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import test.administrator.example.com.mvptest1.framework.MvpPresenter;

/**
 * 备忘录模式->管理备忘录角色
 * Created by thinkpad on 2018/8/2.
 */

@TargetApi(Build.VERSION_CODES.KITKAT)
public class PresenterManager {

	private static final String KEY_ACTIVITY_ID = "test.administrator.example.com.mvptest1.framework.support.manager.PresenterManagerActivtyId";

	//缓存集合->Map集合
	private final static Map<Activity, String> activityIdMap = new HashMap<Activity, String>();
	//缓存Activity
	private final static Map<String, ActivityScopCache> activityScopCacheMap = new HashMap<String, ActivityScopCache>();

	/**
	 * 非常重要的环节
	 * 知识：通过Application监听Activity创建过程
	 */
	private static final Application.ActivityLifecycleCallbacks callbacks = new Application.ActivityLifecycleCallbacks() {

		@Override
		public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
			if (savedInstanceState != null) {
				//需要进行缓存处理
				String activityId = savedInstanceState.getString(KEY_ACTIVITY_ID);
				if (activityId != null) {
					//缓存
					activityIdMap.put(activity, activityId);
				}
			}
		}

		@Override
		public void onActivityStarted(Activity activity) {

		}

		@Override
		public void onActivityResumed(Activity activity) {

		}

		@Override
		public void onActivityPaused(Activity activity) {

		}

		@Override
		public void onActivityStopped(Activity activity) {

		}

		@Override
		public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
			String activityId = activityIdMap.get(activity);
			if (activityId != null) {
				//缓存数据
				outState.putString(KEY_ACTIVITY_ID, activityId);
			}
		}

		@Override
		public void onActivityDestroyed(Activity activity) {
			//释放对象
			if (!activity.isChangingConfigurations()) {
				//需要释放对象
				String activityId = activityIdMap.get(activity);
				if (activityId != null) {
					//获取当前Activity对应的Presenter
					ActivityScopCache scopCache = activityScopCacheMap.get(activityId);
					if (scopCache != null) {
						//释放
						scopCache.clear();
						activityScopCacheMap.remove(activityId);
					}
					if (activityScopCacheMap.isEmpty()) {
						//取消Activity的注册监听
						activity.getApplication().unregisterActivityLifecycleCallbacks(callbacks);
					}
				}
				activityIdMap.remove(activity);
			}
		}
	};

	/**
	 * 规定PresenterManager类中都是类方法，不能存在实例方法
	 */
	private PresenterManager() {
		throw new RuntimeException("运行时异常，这个对象不允许被创建...");
	}

	/**
	 * 简单版本（不一定存在）
	 * 都有用，做了一下抽象。
	 * 如果为空：会做一些相应的逻辑处理
	 *
	 * @param activity
	 * @return
	 */
	protected static ActivityScopCache getActivityScopCache(Activity activity) {
		if (activity != null) {
			throw new NullPointerException("activity空指针异常...");
		}
		String activityId = activityIdMap.get(activity);
		if (activityId == null) {
			return null;
		}
		return activityScopCacheMap.get(activityId);
	}

	/**
	 * 详细版本->得到P缓存管理器（一定存在）
	 * 得到P
	 *
	 * @param activity
	 * @return
	 */
	protected static ActivityScopCache getOrCreateActivityScopCache(Activity activity) {
		if (activity == null) {
			throw new NullPointerException("activity空指针异常...");
		}
		String activityId = activityIdMap.get(activity);
		if (activityId == null) {
			activityId = UUID.randomUUID().toString();
			activityIdMap.put(activity, activityId);
			if (activityIdMap.size() == 1) {
				//注册Activity生命周期的监听器
				activity.getApplication().registerActivityLifecycleCallbacks(callbacks);
			}
		}
		ActivityScopCache activityScopCache = activityScopCacheMap.get(activityId);
		if (activityScopCache == null) {
			activityScopCache = new ActivityScopCache();
			activityScopCacheMap.put(activityId, activityScopCache);
		}
		return activityScopCache;
	}

	/**
	 * 得到具体的Presenter
	 */
	public static <P> P getPresenter(Activity activity, String viewId) {
		if (activity == null) {
			throw new NullPointerException("activity不能为空");
		}
		if (viewId == null) {
			throw new NullPointerException("viewId不能为空");
		}
		ActivityScopCache scopCache = getActivityScopCache(activity);
		return scopCache == null ? null : (P) scopCache.getPresenter(viewId);
	}

	/**
	 * 获取Activity
	 *
	 * @param context
	 * @return
	 */
	public static Activity getActivity(Context context) {
		if (context == null) {
			throw new NullPointerException("context不能为空");
		}
		if (context instanceof Activity) {
			return (Activity) context;
		}
		//循环获取父类类型
		while (context instanceof ContextWrapper) {
			if (context instanceof Activity) {
				return (Activity) context;
			}
			context = ((ContextWrapper) context).getBaseContext();
		}
		//抛出异常
		throw new IllegalStateException("找不到Activity");
	}

	/**
	 * 重置集合
	 */
	protected static void reset() {
		activityIdMap.clear();
		for (ActivityScopCache scopCache : activityScopCacheMap.values()) {
			scopCache.clear();
		}
		activityScopCacheMap.clear();
	}

	/**
	 * 添加Presenter
	 */
	public static void putPresenter(Activity activity, String viewId, MvpPresenter<?> presenter) {
		if (activity == null) {
			throw new NullPointerException("activity不能为空");
		}
		ActivityScopCache scopeCache = getOrCreateActivityScopCache(activity);
		scopeCache.putPresenter(viewId, presenter);
	}

	/**
	 * 删除指定的P
	 */
	public static void remove(Activity activity, String viewId) {
		if (activity == null) {
			throw new NullPointerException("activity不能为空");
		}
		ActivityScopCache scopCache = getActivityScopCache(activity);
		if (scopCache != null) {
			scopCache.remove(viewId);
		}
	}

	/**
	 * 备忘录模式->备份ViewState
	 * 提供get和put方法
	 */
	public static <VS> VS getViewState(@NonNull Activity activity, @NonNull String viewId) {
		if (activity == null) {
			throw new NullPointerException("activity不能为空");
		}
		if (viewId == null) {
			throw new NullPointerException("viewId不能为空");
		}
		ActivityScopCache scopCache = getOrCreateActivityScopCache(activity);
		return scopCache == null ? null : (VS) scopCache.getViewState(viewId);
	}

	public static void putViewState(@NonNull Activity activity, @NonNull String viewId, @NonNull Object viewState) {
		if (activity == null) {
			throw new NullPointerException("activity不能为空");
		}
		if (viewId == null) {
			throw new NullPointerException("viewId不能为空");
		}
		ActivityScopCache scopCache = getOrCreateActivityScopCache(activity);
		scopCache.putViewState(viewId, viewState);
	}

}
